//
// Created on 2023/7/5.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include <bits/alltypes.h>
#define LOG_TAG "testTag [NATIVE]"

#include "data_parser.h"
#include <hilog/log.h>
#include <linux/input-event-codes.h>

#define MIN_BUFFER_SIZE 7

static int g_absXMax = 1;
static int g_absYMax = 1;

static bool g_isKeyDown = false;
static int g_keyIndex = -1;

#define HANDWRITING_ABSPRESSURE_MAX 8191

char outStr[256] = {0};
static void PrintBuffer(const uint8_t *buffer, uint32_t length) {
    int32_t index = 0;
    for (uint32_t idx = 0; idx < length; ++idx) {
        index += sprintf(outStr + index, "%02X ", buffer[idx]);
    }
    OH_LOG_DEBUG(LOG_APP, "recv data len: %{public}u : %{public}s", length, outStr);
}

static void Reset() {
    g_isKeyDown = false;
}

// 单例
DataParser &DataParser::GetInstance() {
    static DataParser parser;
    g_isKeyDown = false;
    return parser;
}

void DataParser::StartWork() {
    simulator_.StartWork();
}

// 更新按键映射键值
void DataParser::UpdateKeyCodeMap(int keyIndex, int keyValue) {
    keyCodeMap_[keyIndex] = keyValue;
}

int32_t DataParser::ParseKeyData(const uint8_t *buffer) {
    g_isKeyDown = true;
    if (buffer[0] == 0x10) {
        g_keyIndex = 0;
    } else {
        g_keyIndex = 1;
    } 
    eventData_.type = EVENT_TYPE_DEF_KEY;
    eventData_.changed = true;
    eventData_.isDown = g_isKeyDown;
    eventData_.keyVal = keyCodeMap_[g_keyIndex];
    return 0;
}

int32_t DataParser::ParseMoveData(const uint8_t *buffer) {
    // 识别滚轮滚动
    if (buffer[5] == 0x01 || buffer[5] == 0xFF) {
        eventData_.type = (buffer[5] == 0x01 ? EVENT_TYPE_WHEEL_UP : EVENT_TYPE_WHEEL_DOWN);
        return 0;
    }
    if (buffer[6] == 0x01 || buffer[6] == 0xFF) {
        eventData_.type = (buffer[6] == 0x01 ? EVENT_TYPE_DEF_WHEEL_UP : EVENT_TYPE_DEF_WHEEL_DOWN);
        return 0;
    }
    if (buffer[1] == 0x00 && buffer[2] == 0x00 && buffer[3] == 0x00 && buffer[4] == 0x00) {
        return 0;
    }
    uint32_t x = (buffer[2] << 24 | buffer[2] << 16 | buffer[2] << 8 | buffer[1]);
    uint32_t y = (buffer[4] << 24 | buffer[4] << 16 | buffer[4] << 8 | buffer[3]);
    if (x==0 && y==0){
        return 0;
    }
    if (g_isKeyDown && eventData_.type == EVENT_TYPE_KEY) {
        eventData_.type = EVENT_TYPE_MOVE_AND_KEY;
    } else {
        eventData_.type = EVENT_TYPE_MOVE;
    }
    eventData_.relX = x;
    eventData_.relY = y;
    return 0;
}

int32_t DataParser::ParseData(const uint8_t *buffer, uint32_t length) {
    PrintBuffer(buffer, length);
    if (length < MIN_BUFFER_SIZE) {
        OH_LOG_ERROR(LOG_APP, "invalid length");
        return -1;
    }
    if (g_isKeyDown && buffer[0] == 0x00) {  // 按键抬起
        eventData_.type = lastData_.type;
        eventData_.changed = true;
        eventData_.isDown = false;
        eventData_.keyVal = lastData_.keyVal;
        g_isKeyDown = false;
    }
    if (isZero(buffer, length)) {
        OH_LOG_INFO(LOG_APP, "type:%{public}d isDown:%{public}d {x:%{public}d, y:%{public}d} key:%{public}d",
                    eventData_.type, eventData_.isDown, eventData_.relX, eventData_.relY, eventData_.keyVal);
        simulator_.ConvertEventData(eventData_);
        return 0;
    }
    int ret = -1;
    if (buffer[0] == 0x10 || buffer[0] == 0x08) { // 罗技鼠标左键
        ret = ParseKeyData(buffer);
        lastData_ = eventData_;
    } else if (buffer[0] == 0x01) {
        g_isKeyDown = true;
        eventData_.type = EVENT_TYPE_KEY;
        eventData_.changed = true;
        eventData_.isDown = g_isKeyDown;
        eventData_.keyVal = BTN_MOUSE;
        lastData_ = eventData_;
    } else if (buffer[0] == 0x02) {
        g_isKeyDown = true;
        eventData_.type = EVENT_TYPE_KEY;
        eventData_.changed = true;
        eventData_.isDown = g_isKeyDown;
        eventData_.keyVal = BTN_RIGHT;
        lastData_ = eventData_;
    } else if (buffer[0] == 0x04) {
        g_isKeyDown = true;
        eventData_.type = EVENT_TYPE_KEY;
        eventData_.changed = true;
        eventData_.isDown = g_isKeyDown;
        eventData_.keyVal = BTN_MIDDLE;
        lastData_ = eventData_;
    }
    ret = ParseMoveData(buffer);
    OH_LOG_INFO(LOG_APP, "type:%{public}d isDown:%{public}d {x:%{public}d, y:%{public}d} key:%{public}d",
                 eventData_.type, eventData_.isDown, eventData_.relX, eventData_.relY, eventData_.keyVal);
    if (ret == 0) {
        simulator_.ConvertEventData(eventData_);
    }
    eventData_.Reset();
    return ret;
}

bool DataParser::isZero(const uint8_t *buffer, uint32_t length) {
    for (uint32_t i = 0; i < length; ++i) {
        if (buffer[i] != 0x00) {
            return false;
        }
    }
    return true;
}
